package com.ljj.hash;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;

public class ConsistentHash {
	
	private Integer vNum=0;
	
	private Map<String,Object> nodes=new HashMap<String,Object>();
	private TreeMap<String,String> vnodes=new TreeMap<String,String>();
	
	public ConsistentHash(){
		this.vNum=200;
		//step();
	}
	
	public ConsistentHash(Integer vNum){
		this.vNum=vNum;
		//step();
	}
	
		
	public Integer getvNum() {
		return vNum;
	}

	public void setvNum(Integer vNum) {
		this.vNum = vNum;
	}

	public void addNode(String key,Object o){
		nodes.put(key, o);
	}
	
	public void addVNode(String key,Object o){
		addNode(key,o);
		String sha1=null;
		for(int i=0;i<vNum;i++){
			sha1=SHA1.getSha1(key+"_"+i);
			vnodes.put(sha1, key);
		}
	}
	
	public Object getNextNode(String tkey){
		String tkeyhash=SHA1.getSha1(tkey);
		String vkey=vnodes.higherKey(tkeyhash);
		if(vkey==null){
			vkey=vnodes.firstKey();
		}
		String nextVKey= getNextVKey(vkey);
		return nodes.get(vnodes.get(nextVKey));
	}
	
	public String getNextVKey(String vkey){
		String key=null;
		String nodeKey=null;
		
		nodeKey=vnodes.get(vkey);
		if(nodeKey==null || nodeKey.trim().equals("")){
			key=vnodes.higherKey(vkey);
			if(key==null){
				key=vnodes.firstKey();
			}
			return getNextVKey(key);
		}else{
			if(nodes.get(nodeKey)==null){
				key=vnodes.higherKey(vkey);
				if(key==null){
					key=vnodes.firstKey();
				}
				return getNextVKey(key);
			}else{
				return vkey;
			}
		}
	}
	
	public Map<String, Object> getNodes() {
		return nodes;
	}

	public TreeMap<String, String> getVnodes() {
		return vnodes;
	}
	
	public void clean(String key){
		nodes.remove(key);
		for(int i=0;i<vNum;i++){
			vnodes.remove(SHA1.getSha1(key+"_"+i));
		}
	}

	public void update(){
		
	}
	

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ConsistentHash c=new ConsistentHash(200);
		c.addVNode("node1", "node1V");
		c.addVNode("node2", "node2V");
		c.addVNode("node3", "node3V");
		for(String s:c.getVnodes().keySet()){
			System.out.print(s+" ");
			System.out.println(c.getVnodes().get(s));
		}
		for(String o:c.getNodes().keySet()){
			System.out.print(o+"_");
			System.out.println(c.getNodes().get(o));
		}
		long t1=System.currentTimeMillis();
		
		System.out.println("next node is "+c.getNextNode("hahah1a")+" ");
		long t2=+(System.currentTimeMillis()-t1);
		System.out.println(t2);
		
		c.clean("node1");
		System.out.println("next node is "+c.getNextNode("hahah1a")+" ");
	}

}
